package com.huitone.smspfm.core.wransms;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.bin.common.utils.DateTimeUtils;
import com.bin.common.utils.StringUtils;
import com.huitone.smspfm.core.config.AppStaticConfigs;
import com.huitone.smspfm.dao.oracle.entity.WarnRecv;
import com.huitone.smspfm.logger.ExtLogger;
import com.huitone.smspfm.socket.client.SocketClient;
import com.huitone.smspfm.socket.protocol.sgip.constant.Constant;
import com.huitone.smspfm.socket.protocol.sgip.message.msgbody.Submit;
import com.huitone.smspfm.socket.protocol.sgip.message.msghead.Head;
import com.huitone.smspfm.socket.utils.SerialUtils;

/**
 * 处理网关网络切换后的告警短信发送任务
 * @author ozh
 *
 */

public class WranSmsSocketTask extends Thread {
	
	private static final ExtLogger logger = ExtLogger.create(WranSmsSocketTask.class);

	
	private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
	
	private int poolSize = 5;
	
	private boolean keepGoing = true;
	
	private SocketClient socketClient;
	
	public static ArrayBlockingQueue<SmsWarnRecvMessage> msgQueue = new ArrayBlockingQueue<SmsWarnRecvMessage>(1000);
	
	private ExecutorService blockingPool = new ThreadPoolExecutor(poolSize, 
			poolSize, 1L, TimeUnit.MINUTES, new ArrayBlockingQueue<>(poolSize * 2), new RejectedExecutionHandler() {
		
		@Override
		public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
			boolean offer = false;
			while(!executor.isShutdown() && !offer) {
				offer = executor.getQueue().offer(r);
				if (!offer) {
					try {
						TimeUnit.MILLISECONDS.sleep(10);
					} catch (InterruptedException e) {}
				}
			}
		}
	});
	
	public WranSmsSocketTask(){}
	
	public void initSocket(String user,String pwd,String srvCode,String ip,int port,int code){		
//		String pawd = new String(Base64.decodeBase64("MjI="));
		socketClient = SocketClient.getInstance();
		socketClient.setMessageHandler(new ClientMessageHandler())
		.setServerIp(ip) // 短信平台的IP地址 (短信平台接口地址)
		.setServerPort(port) // 短信平台的端口号
		.setLoginName(user)  // 用户名 (短信平台分配)
		.setLoginPassword(pwd) // 密码 (短信平台分配)
		.setSrvNode(srvCode) // 业务端编码 (短信平台分配)
		.setCoderule(code); // 业务端编号规则(短信平台分配)
	}
	
	public void initSocket(){
		initSocket(AppStaticConfigs.systemSmsSendUser,
				AppStaticConfigs.systemSmsSendPwd,
				AppStaticConfigs.systemSmsSendSvrNode,
				AppStaticConfigs.systemSmsSendIp,
				StringUtils.toInteger(AppStaticConfigs.systemSmsSendPort),
				StringUtils.toInteger(AppStaticConfigs.systemSmsSendCode));
	}

	
	public boolean send(String user, String srvNode, String serviceCode,
			String sendPort, String smcont,int code) throws IOException {
		// 构造下发短信消息体
		Submit submit = Submit.build(Collections.singletonList(user), // 用户号码,最多一百个
				srvNode, // 业务端编码 (短信平台分配)
				serviceCode, // 业务类型编码 (短信平台分配)
				sendPort, // 发送端口号 (短信平台分配)
				1, // 有三个可选项: 0 该条消息只有最后出错时要返回状态报告; 1 该条消息无论最后是否成功都要返回状态报告;
					// 2-该条消息不需要返回状态报告
				Constant.MessageCodingE.GBK.getValue(), // 默认
				Constant.MessageTypeE.SMS.getValue(), // 默认
				smcont); // 短信内容
		// 构造下发短信消息头
		Head head = Head.build(submit.length(), // 短信消息体长度
				code, // 业务端编号规则 (短信平台分配)
				StringUtils.tolong(DateTimeUtils.dateToStr(new Date(),"MMddHHmmss")), // 时间
				SerialUtils.getSerial()); // 序号从零到Integer.MAX_VALUE循环使用
		if(socketClient == null){
			initSocket();
		}
		return socketClient.sendMsg(head, submit);
	}
	
	public boolean send(String user,String smcont) throws IOException{
		return send(user,
				AppStaticConfigs.systemSmsSendSvrNode,
				AppStaticConfigs.systemSmsSendServiceCode,
				AppStaticConfigs.systemSmsSendSendPort,
				smcont,
				StringUtils.toInteger(AppStaticConfigs.systemSmsSendCode));
	}

	@Override
	public void run() {
		initSocket();
		while( keepGoing && !this.isInterrupted()){
			try {
				if (msgQueue.size() > 0) {
					blockingPool.execute(new Runnable() {

						@Override
						public void run() {
							SmsWarnRecvMessage obj = msgQueue.poll();
							List<WarnRecv> tempObj = new ArrayList<WarnRecv>();// 未发送成功的短信重新加入到列表中
							if (obj != null) {
								List<WarnRecv> users = obj.getUsers();
								String smcont = obj.getSmcont();
								String templateId = obj.getTemplateId();

								if(StringUtils.isEmpty(users) || StringUtils.isEmpty(smcont)){
									logger.error("发送告警时异常出错， 出错内容为 ：" + obj.toString());
									return;
								}
								for (int i = 0; i < users.size(); i++) {
									boolean sendFlag = false;
									WarnRecv warnRecv = users.get(i);
									String userPhone = warnRecv.getPhone();
									String userName = warnRecv.getUserName();
									if(StringUtils.isEmpty(userPhone)){
										logger.error("告警短信错误: 用户手机为空");
										continue;
									}
									if(StringUtils.equals(AppStaticConfigs.Const.SMS_TEMPLATE_TYPE_WGQH,obj.getTemplateId())){
									
										smcont = StringUtils.replace(smcont, "[userNum]", userPhone);
										smcont = StringUtils.replace(smcont, "[time]", dateFormat.format(new Date()));
										smcont = StringUtils.replace(smcont, "[name]", userName);
									}
									
									try {
										sendFlag = send(userPhone,  smcont);
									} catch (IOException e) {
										e.printStackTrace();
										sendFlag = false;
									}

									if (!sendFlag) {
										tempObj.add(users.get(i));
									}
								}
								if (tempObj != null
										&& tempObj.size() > 0) {
									SmsWarnRecvMessage tempWarn = new SmsWarnRecvMessage();
									tempWarn.copy(obj);
									tempWarn.setUsers(tempObj);
									
									msgQueue.offer(tempWarn);
								}
							}
						}
					});
				}

			} catch (Exception e){
				e.printStackTrace();
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {}
			}
		
		logger.info("网络切换告警短信正在退出...");
		if(blockingPool != null){
			blockingPool.shutdown();
			blockingPool = null;
		}
	}
	
	public boolean isKeepGoing() {
		return keepGoing;
	}

	public void setKeepGoing(boolean keepGoing) {
		this.keepGoing = keepGoing;
	}

	@Override
	public void destroy() {
		this.setKeepGoing(false);
		this.interrupt();
		if(blockingPool != null){
			blockingPool.shutdown();
			blockingPool = null;
		}
	}
	
	
	public static void main(String[] args){
		WranSmsSocketTask client = new WranSmsSocketTask();
		client.initSocket("warnSms", "warn123456", "20352", "172.16.7.24", 8901, 10058);
		int num = 0;
		while(true){
			boolean flag = false;
			try {
				flag = client.send("15666595553", "20352", "111", "8080", "测试短信001-"+num, 100058);
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println(flag);
			try {
				Thread.sleep(60000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}
